package com.tyc.aqs;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写锁
 *  将state变量 高16位表示读锁 低16位表示写锁
 *  锁降级  获取写锁-->获取读锁--->释放写锁
 *  写锁获取
 *      存在读锁或者当前线程不是获取写锁则获取失败
 *  写锁释放
 *      与ReentrantLock
 *  读锁获取
 *      若其他线程获取了写锁则获取失败
 *  读锁释放
 *      保证线程安全的将state状态-1
 *
 *   锁降级代码流程如下
 *    需要在获取写锁 且没有释放的时候 获取读锁 然后在释放写锁
 *     目的为了尽早让其他线程可以读取到数据提高吞吐量但不允许其他线程修改
 *
 *
 */
public class ReadWriteLockTest {
    public static volatile boolean update = false;
    private static int cache = 0;
    public static void main(String[] args) throws InterruptedException {
        ReadWriteLock readWriteLock = new ReentrantReadWriteLock(false);
        Lock rLock = readWriteLock.readLock();
        Lock wLock = readWriteLock.writeLock();
        new Thread(() -> {
            for (;;) {
                //保证获取到的是cache的最新值
                rLock.lock();
                if(update){
                    rLock.unlock();
                    wLock.lock();
                    if(update){
                        System.out.println(Thread.currentThread().getName()+"获取cache最新值为:"+cache);
                        update = false;
                    }
                    rLock.lock();
                    wLock.unlock();
                }
                try {
                    //模拟处理数据
                    System.out.println("处理数据："+cache);
                } finally {
                    rLock.unlock();
                }
            }
        }).start();

        new Thread(()->{
            for (;;) {
                wLock.lock();
                try {
                    cache = (int)(Math.random()*100+1);
                    System.out.println(Thread.currentThread().getName()+"更新cache值为:"+cache);
                    update = true;
                } finally {
                    wLock.unlock();
                }
            }
        }).start();
        TimeUnit.SECONDS.sleep(20);
    }

}
